/* $Id: ServiceFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WorkflowDepartment;
import ae.pcfc.etks.online.common.domain.AppMetaData;
import ae.pcfc.etks.online.common.domain.Client;
import ae.pcfc.etks.online.common.domain.ClientServiceRole;
import ae.pcfc.etks.online.common.domain.Service;
import ae.pcfc.etks.online.common.domain.ServiceAttr;
import ae.pcfc.etks.online.common.domain.ServiceAttrValReq;
import ae.pcfc.etks.online.common.domain.ServiceDept;
import ae.pcfc.etks.online.common.domain.ServiceReq;
import ae.pcfc.etks.online.common.domain.ServiceRole;
import ae.pcfc.etks.online.common.domain.TTscClientRole;
import ae.pcfc.etks.online.common.domain.TTscClientRoleToDepartmentMap;
import ae.pcfc.etks.online.common.domain.TTscDepartments;
import ae.pcfc.etks.online.common.domain.User;
import ae.pcfc.etks.online.common.domain.UserServiceSecurity;
import ae.pcfc.etks.online.common.domain.manager.AppMetaDataDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ClientDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessStepActionDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ServiceDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientRoleObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserServiceSecurityDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UtilityDomainObjectManager;
import ae.pcfc.etks.online.common.exception.DuplicateServiceRequestException;
import ae.pcfc.etks.online.common.exception.DuplicateUserNameException;
import ae.pcfc.etks.online.common.exception.InvalidInputException;
import ae.pcfc.etks.online.common.facade.ServiceFacade;
import ae.pcfc.etks.online.common.util.CommonUtils;
import ae.pcfc.etks.online.common.vo.AdminApprovalVO;
import ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO;
import ae.pcfc.etks.online.common.vo.ClientRoleVO;
import ae.pcfc.etks.online.common.vo.DepartmentVO;
import ae.pcfc.etks.online.common.vo.PagingVO;
import ae.pcfc.etks.online.common.vo.ProcessVO;
import ae.pcfc.etks.online.common.vo.SCClientCompanyRoleVO;
import ae.pcfc.etks.online.common.vo.SCClientPersonRoleVO;
import ae.pcfc.etks.online.common.vo.ServiceAttributesVO;
import ae.pcfc.etks.online.common.vo.ServiceRoleVO;
import ae.pcfc.etks.online.common.vo.ServiceVO;
import ae.pcfc.etks.online.common.vo.TrakheesIdVO;
import ae.pcfc.etks.online.common.vo.UserServiceVO;
import ae.pcfc.etks.online.common.vo.UserVO;
import ae.pcfc.etks.online.wf.service.client.UserServiceWF;
import ae.pcfc.etks.online.wf.service.client.vo.LaunchIncidentVO;
import ae.pcfc.etks.online.wf.service.client.vo.UserServiceCompleteStepVO;

public class ServiceFacadeImpl extends BaseFacade implements ServiceFacade {
    	/*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private ServiceDomainObjectManager serviceDomainObjectManager;
	private SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager;
	private SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager;
	private AppMetaDataDomainObjectManager appMetaDataDomainObjectManager;
	private ProcessDomainObjectManager processDomainObjectManager;
	private UserDomainObjectManager userDomainObjectManager;
	private UserServiceSecurityDomainObjectManager userServiceSecurityDomainObjectManager;
	private ClientDomainObjectManager clientDomainObjectManager;
	private SingleClientRoleObjectManager singleClientRoleObjectManager;
	private UtilityDomainObjectManager utilityDomainObjectManager;
	//private UserAnnouncementDomainObjectManager userAnnouncementDomainObjectManager;
	private UserServiceWF userServiceWF;
	
	private ProcessStepActionDomainObjectManager processStepActionDomainObjectManager;
	
	public ProcessStepActionDomainObjectManager getProcessStepActionDomainObjectManager() {
		return processStepActionDomainObjectManager;
	}

	public void setProcessStepActionDomainObjectManager(
			ProcessStepActionDomainObjectManager processStepActionDomainObjectManager) {
		this.processStepActionDomainObjectManager = processStepActionDomainObjectManager;
	}

	public SingleClientRoleObjectManager getSingleClientRoleObjectManager() {
		return singleClientRoleObjectManager;
	}

	public void setSingleClientRoleObjectManager(
			SingleClientRoleObjectManager singleClientRoleObjectManager) {
		this.singleClientRoleObjectManager = singleClientRoleObjectManager;
	}

	public UtilityDomainObjectManager getUtilityDomainObjectManager() {
		return utilityDomainObjectManager;
	}

	public void setUtilityDomainObjectManager(
			UtilityDomainObjectManager utilityDomainObjectManager) {
		this.utilityDomainObjectManager = utilityDomainObjectManager;
	}
	public void setServiceDomainObjectManager(
			ServiceDomainObjectManager serviceDomainObjectManager) {

		this.serviceDomainObjectManager = serviceDomainObjectManager;
	}

	public void setSingleClientPersonDomainObjectManager(
			SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager) {
		this.singleClientPersonDomainObjectManager = singleClientPersonDomainObjectManager;
	}

	public void setAppMetaDataDomainObjectManager(
			AppMetaDataDomainObjectManager appMetaDataDomainObjectManager) {
		this.appMetaDataDomainObjectManager = appMetaDataDomainObjectManager;
	}

	public void setProcessDomainObjectManager(
			ProcessDomainObjectManager processDomainObjectManager) {
		this.processDomainObjectManager = processDomainObjectManager;
	}

	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}

	public void setUserServiceSecurityDomainObjectManager(
			UserServiceSecurityDomainObjectManager userServiceSecurityDomainObjectManager) {
		this.userServiceSecurityDomainObjectManager = userServiceSecurityDomainObjectManager;
	}

	public void setSingleClientCompanyDomainObjectManager(
			SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager) {
		this.singleClientCompanyDomainObjectManager = singleClientCompanyDomainObjectManager;
	}

	public void setClientDomainObjectManager(
			ClientDomainObjectManager clientDomainObjectManager) {
		this.clientDomainObjectManager = clientDomainObjectManager;
	}

/*	public void setUserAnnouncementDomainObjectManager(
			UserAnnouncementDomainObjectManager userAnnouncementDomainObjectManager) {
		this.userAnnouncementDomainObjectManager = userAnnouncementDomainObjectManager;
	}*/

	public void setUserServiceWF(UserServiceWF userServiceWF) {
		this.userServiceWF = userServiceWF;
	}

	/**
	 * registerUserServiceList
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#registerUserServiceList(ae.pcfc.etks.online.common.vo.UserServiceVO)
	 * 
	 */
	public boolean registerUserServiceList(UserServiceVO userServiceVO) {
		if (userServiceVO != null) {
			if (userServiceVO.getlServiceVO() == null) {
				userServiceVO.setlServiceVO(new ArrayList<Long>());
			}
			// Add Company Employee Default Service to the User
			Service employeeDefaultService = serviceDomainObjectManager
					.findServiceByServiceDefault(ConstantsCommon.COMPANY_EMPLOYEE_DEFAULT_SERVICE);
			if (employeeDefaultService != null) {
				userServiceVO.getlServiceVO().add(
						employeeDefaultService.getServiceId());
			}

			for (Long lServiceId : userServiceVO.getlServiceVO()) {
				Service services = serviceDomainObjectManager
						.getServiceByPrimaryKey(lServiceId);
				if (services != null) {
					for (ServiceRole ServiceRole : services.getServiceRoles()) {
						UserServiceSecurity userServiceSecurity = new UserServiceSecurity();
						userServiceSecurity.setServiceRole(ServiceRole);
						userServiceSecurity.setUsSecurityUsername(userServiceVO
								.getStrUserName());
						userServiceSecurity.setUsSecurityUserType(userServiceVO
								.getStrUserType());
						userServiceSecurityDomainObjectManager
								.add(userServiceSecurity);
					}
				}
			}
		}
		return true;
	}
	/**
	 * Description:
	 * updateUserServiceList:	Implementation of updating the UserServiceSecuirty records for a user based on his Services
	 *
	 * @author Dicetek.Ismail
	 * @param	UserServiceVO - Contains the information about the User and the Services selected/deselected fromt the front end
	 * @return	returns true on success
	 * 
	 */	
	public boolean updateUserServiceList(UserServiceVO userServiceVO) {

		List<UserServiceSecurity> lSubSetUserServiceSecurity = new ArrayList<UserServiceSecurity>();

		// Find the User Service Security records except those related to the Default Services, 
		//so that when updating the services, the default services are not affected
		List<UserServiceSecurity> lDbUserServiceSecurity = userServiceSecurityDomainObjectManager

		.findByUserNameWithoutDefault(userServiceVO.getStrUserName(),
				new String[] {
						ConstantsCommon.COMPANY_EMPLOYEE_DEFAULT_SERVICE,
						ConstantsCommon.COMPANY_ADMIN_DEFAULT_SERVICE });

		if (userServiceVO != null && userServiceVO.getlServiceVO() != null
				&& userServiceVO.getlServiceVO().size() > 0) {
			for (Long lServiceId : userServiceVO.getlServiceVO()) {
				Service services = serviceDomainObjectManager
						.getServiceByPrimaryKey(lServiceId);
				if (services != null) {
					for (ServiceRole ServiceRole : services.getServiceRoles()) {
						UserServiceSecurity uss = findByServiceRoleAndUserName(
								lDbUserServiceSecurity, ServiceRole,
								userServiceVO.getStrUserName());
						if (uss == null) {
							UserServiceSecurity userServiceSecurity = new UserServiceSecurity();
							userServiceSecurity.setServiceRole(ServiceRole);
							userServiceSecurity
									.setUsSecurityUsername(userServiceVO
											.getStrUserName());
							userServiceSecurity
									.setUsSecurityUserType(userServiceVO
											.getStrUserType());
							userServiceSecurityDomainObjectManager
									.add(userServiceSecurity);
						} else {
							lSubSetUserServiceSecurity.add(uss);
						}
					}
				}
			}

		}
		//Logic to find the list of already existing uss which are not in the list from the front end
		//Find the union of uss objects  and  subtract it from the uss objects from front end which already exist in db
		//from which we get the uss objects which existed in the db initially and now it is removed from the front end
		if (lDbUserServiceSecurity != null) {
			@SuppressWarnings("unchecked")
			List<UserServiceSecurity> lUnionUserServiceSecurity = (List<UserServiceSecurity>) CommonUtils
					.union(lDbUserServiceSecurity, lSubSetUserServiceSecurity);
			@SuppressWarnings("unchecked")
			List<UserServiceSecurity> lRemoveUserServiceSecurity = (List<UserServiceSecurity>) CommonUtils
					.subtract(lUnionUserServiceSecurity,
							lSubSetUserServiceSecurity);
			//Delete the list of uss objects
			for (UserServiceSecurity uss : lRemoveUserServiceSecurity) {
				userServiceSecurityDomainObjectManager.delete(uss);
			}

		}

		return true;
	}

	/**
	 * findByServiceRoleAndUserName
	 * 
	 * @param lDbUserServiceSecurity
	 * @param serviceRole
	 * @param userName
	 * @return
	 * UserServiceSecurity
	 */
	public UserServiceSecurity findByServiceRoleAndUserName(
			List<UserServiceSecurity> lDbUserServiceSecurity,
			ServiceRole serviceRole, String userName) {
		if (lDbUserServiceSecurity == null
				|| lDbUserServiceSecurity.size() == 0) {
			return null;
		}
		for (UserServiceSecurity userServiceSecurity : lDbUserServiceSecurity) {
			if (userServiceSecurity.getServiceRole().equals(serviceRole)) {
				return userServiceSecurity;
			}
		}
		return null;
	}

	/**
	 * registerService
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#registerService(ae.pcfc.etks.online.common.vo.ServiceVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public boolean registerService(ServiceVO serviceVO) {

		Service services = new Service();
		getMapper().map(serviceVO, services);

		// We have to set for service ids
		if(services.getServiceAttrs() != null){
			for (ServiceAttr attr : services.getServiceAttrs()) {
				attr.setService(services);
				attr.setServiceAttrStatus(ConstantsCommon.ACTIVE);
			}
		}

		Set<ServiceDept> serviceDepts = new HashSet<ServiceDept>();

		ServiceDept serviceDept;

		if (serviceVO.getArrServiceDeptsCode() != null
				&& serviceVO.getArrServiceDeptsCode().size() > 0) {
			for (String dept : serviceVO.getArrServiceDeptsCode()) {
				serviceDept = new ServiceDept();
				serviceDept.setService(services);
				serviceDept.setSDeptCode(dept);

				serviceDepts.add(serviceDept);
			}
		}

		if (serviceDepts.size() > 0)
			services.setServiceDepts(serviceDepts);

		Set<ServiceRole> serviceRoles = new HashSet<ServiceRole>();

		ServiceRole serviceRole;
		
		if(serviceVO.getArrServiceRole()!= null){
			for (Integer iServiceRole : serviceVO.getArrServiceRole()) {
				serviceRole = new ServiceRole();
				serviceRole.setService(services);
				serviceRole.setRoleId(iServiceRole.longValue());
				serviceRole.setSrSecurityRoleName(serviceVO.getStrServiceSecRole());
				serviceRoles.add(serviceRole);
			}
		}

		if (serviceRoles.size() > 0)
			services.setServiceRoles(serviceRoles);

		serviceDomainObjectManager.add(services);

		// if the service is default then client admin should be assigned the
		// service role and users should be assigned with user service security
		if (serviceVO.getStrDefaultService() != null) {

			for (ServiceRole ServiceRole : services.getServiceRoles()) {

				List<TrakheesIdVO> trakheesIdVOs = this.singleClientPersonDomainObjectManager
						.findSCTrakheesIdsByRoleId(ServiceRole.getRoleId()
								.toString());

				if (trakheesIdVOs != null && trakheesIdVOs.size() > 0) {

					int size = trakheesIdVOs.size() > 1000 ? 1000
							: trakheesIdVOs.size();
					
					for (int i = 0; i + size <= trakheesIdVOs.size(); i =  i + 1000) {

						List<Client> clients = this.clientDomainObjectManager
								.findByTrakheesIds(trakheesIdVOs.subList(i, i
										+ size));
						if (clients != null && clients.size() > 0) {
							for (Client client : clients) {

								ClientServiceRole clientServiceRole = new ClientServiceRole();

								clientServiceRole.setClient(client);
								clientServiceRole.setServiceRole(ServiceRole);

								this.clientDomainObjectManager
										.addClientServiceRole(clientServiceRole);

								for (User user : client.getUsers()) {
									if(!ConstantsCommon.COMPANY_EMPLOYEE.equalsIgnoreCase(user.getUType())){
										UserServiceSecurity userServiceSecurity = new UserServiceSecurity();
										userServiceSecurity
												.setServiceRole(ServiceRole);
										userServiceSecurity
												.setUsSecurityUsername(user
														.getUUsername());
										userServiceSecurity
												.setUsSecurityUserType(user
														.getUType());
	
										this.userServiceSecurityDomainObjectManager
												.add(userServiceSecurity);
									}
								}
							}
						}
						//
						if(size == 1000 && trakheesIdVOs.subList(i, trakheesIdVOs.size()).size() - 1000 < 1000){
						    size = trakheesIdVOs.subList(i, trakheesIdVOs.size()).size() - 1000;
						}
					}

				}
			}
		}

		return true;
	}

	/**
	 * serviceUpdate
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#serviceUpdate(ae.pcfc.etks.online.common.vo.ServiceVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public boolean serviceUpdate(ServiceVO serviceVO) {
		// TODO Auto-generated method stub
		Service services = this.serviceDomainObjectManager.getServiceByPrimaryKey(serviceVO.getStrServiceID());
		if(services == null)
			return false;
		// set only the following fields from the front end object as the other fields are readonly
		services.setServiceNameEng(serviceVO.getStrServiceNameEng());
		services.setServiceNameArb(serviceVO.getStrServiceNameArb());
		services.setServiceURL(serviceVO.getStrServiceURL());
		services.setServiceDefaultDeptCode(serviceVO.getStrServiceOwner());

		Set<ServiceAttr> serviceAttrs = new HashSet<ServiceAttr>();
		
		if(serviceVO.getArrServiceAttributes() != null){
			for (ServiceAttributesVO attrVO : serviceVO.getArrServiceAttributes()) {
				ServiceAttr attr = new ServiceAttr();
				this.getMapper().map(attrVO, attr);
				attr.setService(services);
				serviceAttrs.add(attr);
			}
		}
		
		services.setServiceAttrs(serviceAttrs);
		
		Set<ServiceDept> serviceDepts = new HashSet<ServiceDept>();

		ServiceDept serviceDept;

		if (serviceVO.getArrServiceDeptsCode() != null
				&& serviceVO.getArrServiceDeptsCode().size() > 0) {
			for (String dept : serviceVO.getArrServiceDeptsCode()) {
				if(services.getServiceDepts() != null && services.getServiceDepts().size() > 0){
					serviceDept = getServiceDept(services.getServiceDepts(), dept);
					if(serviceDept == null) {
						serviceDept = new ServiceDept();
						serviceDept.setService(services);
						serviceDept.setSDeptCode(dept);
					}
					serviceDepts.add(serviceDept);
				}
			}
		}

		if (serviceDepts.size() > 0){
			services.getServiceDepts().clear();
			services.getServiceDepts().addAll(serviceDepts);
		}

		this.serviceDomainObjectManager.update(services);	
			
		return true;
	}

	/**
	 * Description:
	 * getServiceDept:	Utility method to find the Service Department from the set of Service Departments 
	 *
	 * @author Dicetek.Ismail
	 * @param	Set<ServiceDept> - The set in which the ServiceDepartment needs to be searched
	 * @param	String department code to be searched in the Set
	 * @return	returns the Service Department if found in the Set, 
	 * 				Else returns null 
	 * 
	 */	
	private ServiceDept getServiceDept(Set<ServiceDept> serviceDepts,String deptCode) {
		// TODO Auto-generated method stub
		if(serviceDepts != null && deptCode != null){
			for(ServiceDept serviceDept : serviceDepts){
				if(serviceDept.getSDeptCode().equalsIgnoreCase(deptCode)){
					return serviceDept;
				}
			}
		}
		return null;
	}

	/**
	 * deleteServiceById
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#deleteServiceById(java.lang.Long)
	 * 
	 */
	@Transactional
	public boolean deleteServiceById(Long Id) {
		Service service = this.serviceDomainObjectManager
				.findByPrimaryKey((String.valueOf(Id)));
		service.setServiceStatus(ConstantsCommon.DISABLE);
		this.serviceDomainObjectManager.update(service);
		return true;
	}

	/**
	 * getServicesList
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#getServicesList()
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> getServicesList() {

		List<Service> services = serviceDomainObjectManager.getServicesList();

		List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();

		ServiceVO serviceVO;
		// TODO: Mapper has to be used below
		for (Service service : services) {
			serviceVO = new ServiceVO();
			serviceVO.setStrServiceID(service.getServiceId());
			serviceVO.setStrServiceNameEng(service.getServiceNameEng());
			serviceVO.setStrServiceNameArb(service.getServiceNameArb());
			serviceVOs.add(serviceVO);
		}
		return serviceVOs;
	}

	/**
	 * getServiceByPrimaryKey
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#getServiceByPrimaryKey(java.lang.Long)
	 * 
	 */
	@Transactional(readOnly = true)
	public ServiceVO getServiceByPrimaryKey(Long Id) {

		Service services = serviceDomainObjectManager
				.getServiceByPrimaryKey(Id);
		ServiceVO vo = new ServiceVO();

		if (null != services) {

			this.getMapper().map(services, vo);
			/*Set<ServiceAttr> serviceAttrs = services.getServiceAttrs();
			// Mapper has to be used below
			for (ServiceAttr serviceAttr : serviceAttrs) {
				if (null != serviceAttr.getServiceAttrArb())
					vo.setStrServiceAttributeNameArb(serviceAttr
							.getServiceAttrArb());
				if (null != serviceAttr.getServiceAttrEng())
					vo.setStrServiceAttributeNameEng(serviceAttr
							.getServiceAttrEng());
				if (null != serviceAttr.getServiceAttrNecessity())
					vo.setStrNeccessity(serviceAttr.getServiceAttrNecessity());

			}*/

			/*
			 * Iterator<ServiceAttr> itrServiceAttr =
			 * onlineServices.getServiceAttrs().iterator();
			 * while(itrServiceAttr.hasNext()) { if(null !=
			 * itrServiceAttr.next().getServiceAttrArb())
			 * vo.setStrServiceAttributeNameArb
			 * (itrServiceAttr.next().getServiceAttrArb()); if(null !=
			 * itrServiceAttr.next())
			 * vo.setStrServiceAttributeNameEng(itrServiceAttr
			 * .next().getServiceAttrEng()); if(null !=
			 * itrServiceAttr.next().getServiceAttrNecessity())
			 * vo.setStrNeccessity
			 * (itrServiceAttr.next().getServiceAttrNecessity()); }
			 */
			if(services.getServiceDefaultDeptCode() != null){
				TTscDepartments ttscDepartments = this.utilityDomainObjectManager.getDepartmentById(services.getServiceDefaultDeptCode());
				if(ttscDepartments != null){
					DepartmentVO defaultDepartment = new DepartmentVO();
					this.getMapper().map(ttscDepartments, defaultDepartment);
					if(defaultDepartment != null){
						vo.setDefaultDepartment(defaultDepartment);
					}
				}
			}
			Iterator<ServiceRole> itrServiceRole = services.getServiceRoles()
					.iterator();
			ServiceRole serviceRole = new ServiceRole();
			List<Integer> roleList;
			roleList = new ArrayList<Integer>();
			
			while (itrServiceRole.hasNext()) {
				serviceRole = itrServiceRole.next();
				roleList.add((serviceRole.getRoleId()).intValue());
				vo.setArrServiceRole(roleList);
				vo.setStrServiceSecRole(serviceRole.getSrSecurityRoleName());
			}

			Iterator<ServiceDept> itrServiceDept = services.getServiceDepts()
					.iterator();
			ServiceDept serviceDept = new ServiceDept();
			List<String> deptList;
			deptList = new ArrayList<String>();

			while (itrServiceDept.hasNext()) {
				serviceDept = itrServiceDept.next();
				deptList.add(serviceDept.getSDeptCode());
				vo.setArrServiceDeptsCode(deptList);
			}

		}
		if (null != services.getServiceNameArb())
			vo.setStrServiceNameArb(services.getServiceNameArb());
		if (null != services.getServiceNameEng())
			vo.setStrServiceNameEng(services.getServiceNameEng());

		return vo;
	}

	/**
	 * findServiceByUserNameAndTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceByUserNameAndTrakheesId(java.lang.String, java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> findServiceByUserNameAndTrakheesId(String userName,
			String trakheesId) {

		String[] clientId = trakheesId.split("-");

		if (clientId[0].equals(ConstantsCommon.PERSON)) {
			List<SCClientPersonRoleVO> clientPersonRoleVOs = this.singleClientPersonDomainObjectManager
					.findSCPersonRoleByTrakheesId(trakheesId);
			if (clientPersonRoleVOs != null && clientPersonRoleVOs.size() > 0) {
				List<Long> roleIds = new ArrayList<Long>();

				for (SCClientPersonRoleVO role : clientPersonRoleVOs) {
					roleIds.add(role.getCrId());
				}

				List<Service> services = null;

				if (roleIds != null && roleIds.size() > 0)
					services = this.serviceDomainObjectManager
							.findServiceAvailableByUserNameAndRoleIds(userName,
									roleIds);

				if (services != null && services.size() > 0) {
					List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();
					ServiceVO serviceVO = null;

					for (Service serv : services) {
						serviceVO = new ServiceVO();
						getMapper().map(serv, serviceVO);
						serviceVOs.add(serviceVO);
					}

					return serviceVOs;
				}
			}
		} else {

			List<SCClientCompanyRoleVO> clientCompanyRoleVOs = this.singleClientCompanyDomainObjectManager
					.findSCCompanyRoleByTrakheesId(trakheesId);
			if (clientCompanyRoleVOs != null && clientCompanyRoleVOs.size() > 0) {
				List<Long> roleIds = new ArrayList<Long>();

				for (SCClientCompanyRoleVO role : clientCompanyRoleVOs) {
					roleIds.add(role.getCrId());
				}

				List<Service> services = null;

				if (roleIds != null && roleIds.size() > 0)
					services = this.serviceDomainObjectManager
							.findServiceAvailableByUserNameAndRoleIds(userName,
									roleIds);

				if (services != null && services.size() > 0) {
					List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();
					ServiceVO serviceVO = null;

					for (Service serv : services) {
						serviceVO = new ServiceVO();
						getMapper().map(serv, serviceVO);
						serviceVOs.add(serviceVO);
					}

					return serviceVOs;
				}
			}

		}

		return null;
	}

	/**
	 * addServiceReq
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#addServiceReq(java.lang.String, java.util.List, ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO)
	 * 
	 */
	@Transactional
	public String addServiceReq(String strUserName, List<ServiceVO> serviceVOs, AppMetaDataDetailVO appMetaDataVO) {
		User user = this.userDomainObjectManager.findUserByUserName(strUserName);
		AppMetaData appMetaData = new AppMetaData();
		ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager.getProcessByProcessAndStepCode(appMetaDataVO.getProcessCode().getProcessCode(), appMetaDataVO.getStrProcessStep());
		appMetaData.setProcess(process);
		getMapper().map(appMetaDataVO, appMetaData);
		appMetaData.setUserId(user.getUId());
		appMetaData.setClientId(user.getClient().getCId());
		for (ServiceVO serviceVO : serviceVOs) {
			ServiceReq serviceReq = new ServiceReq();
			serviceReq.setApplicationId(appMetaData.getApplicationId());
			serviceReq.setUser(user);
			serviceReq.setServiceNameEng(serviceVO.getStrServiceNameEng());
			serviceReq.setServiceNameArb(serviceVO.getStrServiceNameArb());
			Service service = this.serviceDomainObjectManager.findByPrimaryKey(serviceVO.getStrServiceID().toString());
			Set<ServiceAttrValReq> valReqs = new HashSet<ServiceAttrValReq>();

			if (service != null)
				serviceReq.setService(service);

			Set<ServiceAttr> attrs = service.getServiceAttrs();
			ServiceAttrValReq serviceAttrValReq;
			for (ServiceAttr attr : attrs) {
				serviceAttrValReq = new ServiceAttrValReq();
				serviceAttrValReq.setApplicationId(appMetaData.getApplicationId().toString());
				for (ServiceAttributesVO vo : serviceVO.getArrServiceAttributes()) {
					if(ConstantsCommon.ACTIVE.equalsIgnoreCase(vo.getServiceAttrStatus())){
						if (new Long(vo.getiAttrId()).compareTo(attr.getServiceAttrId()) == 0) {
							serviceAttrValReq.setServiceAttr(attr);
							serviceAttrValReq.setServiceReq(serviceReq);
							serviceAttrValReq.setUser(user);
							serviceAttrValReq.setServiceAttrValue(vo.getStrAttrValue());
							serviceAttrValReq.setServiceAttrEng(attr.getServiceAttrEng());
							serviceAttrValReq.setServiceAttrArb(attr.getServiceAttrArb());
							serviceAttrValReq.setServiceAttrNecessity(attr.getServiceAttrNecessity());
							valReqs.add(serviceAttrValReq);
						}
					}
				}
			}
			serviceReq.setServiceAttrValReqs(valReqs);
			if (this.serviceDomainObjectManager.findServiceReqByUserAndServiceId(user.getUId(),service.getServiceId()) == null) {
				this.serviceDomainObjectManager.addServiceReq(serviceReq);
			} else {
				throw new DuplicateServiceRequestException(service.getServiceNameEng());
			}
		}
		appMetaDataDomainObjectManager.add(appMetaData);
		return appMetaData.getClientRefNo();
	}

	/**
	 * findServiceListByIds
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceListByIds(java.util.List)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> findServiceListByIds(List<Long> ids) {

		List<Service> services = this.serviceDomainObjectManager
				.findServiceListByIds(ids);

		if (services != null && services.size() > 0) {
			List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();
			ServiceVO serviceVO = null;

			for (Service serv : services) {
				serviceVO = new ServiceVO();
				getMapper().map(serv, serviceVO);
				serviceVOs.add(serviceVO);
			}

			return serviceVOs;
		}
		return null;
	}

	/**
	 * findServiceRequestByApplicationId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceRequestByApplicationId(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> findServiceRequestByApplicationId(String applicationId) {

		List<ServiceReq> serviceReqs = this.serviceDomainObjectManager
				.findServiceReqByApplicationId(applicationId);

		List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();

		ServiceVO serviceVO;

		for (ServiceReq serviceReq : serviceReqs) {

			serviceVO = new ServiceVO();
			//getMapper().map(serviceReq.getService(), serviceVO);

			// Set<ServiceAttrValReq> attrValReqs =
			// serviceReq.getServiceAttrValReqs();
			// Setting the value on the index
			/*for (ServiceAttributesVO attributesVO : serviceVO
					.getArrServiceAttributes()) {
				for (ServiceAttrValReq attrValReq : serviceReq
						.getServiceAttrValReqs()) {
					Long attrId = new Long(attributesVO.getiAttrId());

					if (attrId.compareTo(attrValReq.getServiceAttr()
							.getServiceAttrId()) == 0) {

						attributesVO.setStrAttrValue(attrValReq
								.getServiceAttrValue());
					}

				}
			}*/
			getMapper().map(serviceReq, serviceVO);
			serviceVO.setStrServiceID(serviceReq.getService().getServiceId());
			List<ServiceAttributesVO> arrServiceAttributes = new ArrayList<ServiceAttributesVO>();
			for (ServiceAttrValReq attrValReq : serviceReq.getServiceAttrValReqs()) {
				ServiceAttributesVO attributesVO = new ServiceAttributesVO();
				this.getMapper().map(attrValReq, attributesVO);
				arrServiceAttributes.add(attributesVO);
			}
			serviceVO.setArrServiceAttributes(arrServiceAttributes);
			serviceVOs.add(serviceVO);
		}

		return serviceVOs;
	}

	/**
	 * reviewRegisterService
	 * @return 
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#reviewRegisterService(ae.pcfc.etks.online.common.vo.AdminApprovalVO)
	 * 
	 */
	@Transactional
	public UserServiceCompleteStepVO reviewRegisterService(AdminApprovalVO adminApprovalVO) {
		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			/************ Storing Meta Data in Tables ***********************/
            	    	if(appMetaDataDomainObjectManager.validateAppMetaDataWithStep(appMetaData,adminApprovalVO.getStrStepName())){
        	    	    throw new InvalidInputException();
        	    	}
			String wfStatusEn = appMetaData.getWfStatusEn();
			String wfStatusAr = appMetaData.getWfStatusAr();
			getMapper().map(adminApprovalVO, appMetaData);
			appMetaData.setWfStatusEn(wfStatusEn);
			appMetaData.setWfStatusAr(wfStatusAr);
			this.appMetaDataDomainObjectManager.updateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());
			/************** End Store Meta Date ***************************/
			UserServiceCompleteStepVO completeStepVO = getCompleteStepVO(adminApprovalVO, appMetaData);

			if(userServiceWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
			    	addRequestedServices(adminApprovalVO);
        			appMetaData.setWfStatus(ConstantsCommon.APPROVE);
        			appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
        			appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
        			userServiceWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by any other departments, send the approval message to the Ultimus alone
				userServiceWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.REJECT)){
			    	// If Rejected, update the application request in DB as rejected and send the rejection message to the Ultimus
			    	appMetaData.setWfStatus(ConstantsCommon.REJECT);
				appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
				appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
				userServiceWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_REJECT, adminApprovalVO.getStrUserNotification());
			}
			appMetaDataDomainObjectManager.update(appMetaData);
			return completeStepVO;
		}
		return null;
	}
	private void addRequestedServices(AdminApprovalVO adminApprovalVO) {
		UserServiceSecurity userServiceSecurity;
		User user = null;
		List<ServiceReq> serviceReqs = this.serviceDomainObjectManager.findServiceReqByApplicationId(adminApprovalVO.getStrApplicationId());
		if(serviceReqs != null){
			for (ServiceReq service : serviceReqs) {
	
				Client client = service.getUser().getClient();
				ClientServiceRole clientServiceRole;
				user = service.getUser();
				for (ServiceRole serviceRole : service.getService().getServiceRoles()) {
					clientServiceRole = new ClientServiceRole();
					clientServiceRole.setClient(client);
					clientServiceRole.setServiceRole(serviceRole);
	
					this.clientDomainObjectManager.addClientServiceRole(clientServiceRole);
	
					// For User Service Security
					userServiceSecurity = new UserServiceSecurity();
					userServiceSecurity.setServiceRole(serviceRole);
					userServiceSecurity.setUsSecurityUsername(service.getUser().getUUsername());
					userServiceSecurity.setUsSecurityUserType(service.getUser().getUType());
					// userServiceSecurities.add(userServiceSecurity);
	
					this.userServiceSecurityDomainObjectManager.add(userServiceSecurity);
	
				}
			}
		}
	}
	/**
	 * getCompleteStepVO
	 * To get the CompleteStepVO with the values populated
	 * @param adminApprovalVO
	 * @param appMetaData
	 * @return
	 * ClientRoleCompleteStepVO
	 */
	private UserServiceCompleteStepVO getCompleteStepVO(AdminApprovalVO adminApprovalVO, AppMetaData appMetaData) {
		UserServiceCompleteStepVO completeStepVO = new UserServiceCompleteStepVO();
		completeStepVO.setgApplicationID(adminApprovalVO.getStrApplicationId());
		completeStepVO.setgClientReference(appMetaData.getClientRefNo());
		completeStepVO.setStrStepName(adminApprovalVO.getStrStepName());
		completeStepVO.setStrUserName(adminApprovalVO.getStrUserName());

		if (appMetaData.getUserId() != null) {
			User user = this.userDomainObjectManager.findByPrimaryKey(appMetaData.getUserId().toString());
			if (user != null) {
				completeStepVO.setgName(user.getUNameEng());
				completeStepVO.setgEmail(user.getUEmail());
			}

		}
		completeStepVO.setnIncidentNumber(Integer.parseInt(adminApprovalVO.getStrIncidentNo()));
		return completeStepVO;
	}
	/**
	 * findServiceListByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceListByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> findServiceListByUserName(String userName) {

		List<Service> services = this.serviceDomainObjectManager
				.findServiceListByUserName(userName);

		if (services != null && services.size() > 0) {
			List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();
			ServiceVO serviceVO = null;

			for (Service serv : services) {
				serviceVO = new ServiceVO();
				getMapper().map(serv, serviceVO);
				serviceVOs.add(serviceVO);
			}

			return serviceVOs;
		}
		return null;
	}

	/**
	 * getServicesListByPagingVO
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#getServicesListByPagingVO(ae.pcfc.etks.online.common.vo.PagingVO)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceVO> getServicesListByPagingVO(PagingVO pagingVO) {

		List<Service> services = this.serviceDomainObjectManager
				.getServicesListByPagingVO(pagingVO);

		if (services != null && services.size() > 0) {
			List<ServiceVO> serviceVOs = new ArrayList<ServiceVO>();
			ServiceVO serviceVO = null;

			for (Service serv : services) {
				serviceVO = new ServiceVO();
				getMapper().map(serv, serviceVO);
				serviceVOs.add(serviceVO);
			}

			return serviceVOs;
		}

		return null;

	}
	/**
	 * registerEmployee
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#registerEmployee(ae.pcfc.etks.online.common.vo.UserVO, ae.pcfc.etks.online.common.vo.UserServiceVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public void registerEmployee(UserVO userVO, UserServiceVO userServiceVO) {
		if (validateUserVO(userVO)) {
			User user = new User();
			getMapper().map(userVO, user);
			this.userDomainObjectManager.add(user);
			registerUserServiceList(userServiceVO);
		}
	}
	/**
	 * Description:
	 * validateUserVO:	Utility method to validate the user
	 * Checks whether the username and email already exists 
	 *
	 * @author Dicetek.Ismail
	 * @param	UserVO - Contains the information of the User obtained from the front end
	 * @return	- returns true on success
	 * 
	 */	
	private boolean validateUserVO(UserVO userVO) {
		// TODO Auto-generated method stub
		User user = userDomainObjectManager.findUserByUserName(userVO
				.getStrUsrName());
		if (user != null) {
			throw new DuplicateUserNameException(userVO.getStrUsrName());
		}
		/*user = userDomainObjectManager.findUserByEmailExceptCurrentCompany(userVO.getStrEmail(),userVO.getClient().getStrTrakheesId());
		if (user != null) {
			throw new DuplicateUserEmailException(userVO.getStrEmail());
		}*/
		return true;
	}

	/**
	 * updateEmployee
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#updateEmployee(ae.pcfc.etks.online.common.vo.UserVO, ae.pcfc.etks.online.common.vo.UserServiceVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public void updateEmployee(UserVO userVO, UserServiceVO userServiceVO) {
		if (validateEditUserVO(userVO)) {
			User user = new User();
			getMapper().map(userVO, user);
			this.userDomainObjectManager.update(user);
			if (userServiceVO != null) {
				updateUserServiceList(userServiceVO);
			}
		}
	}
	/**
	 * Description:
	 * validateUserVO:	Utility method to validate the user when editing the employee
	 * Checks whether the email already exists 
	 *
	 * @author Dicetek.Ismail
	 * @param	UserVO - Contains the information of the User obtained from the front end
	 * @return	- returns true on success
	 * 
	 */	
	private boolean validateEditUserVO(UserVO userVO) {
		// TODO Auto-generated method stub
		/*User user = userDomainObjectManager.findUserByEmailExceptCurrentCompany(
				userVO.getStrEmail(), userVO.getClient().getStrTrakheesId());
		if (user != null) {
			throw new DuplicateUserEmailException(userVO.getStrEmail());
		}*/

		return true;
	}

	/**
	 * findClientRolesByRoleIds
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findClientRolesByRoleIds(java.util.List)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ClientRoleVO> findClientRolesByRoleIds(List<Integer> roleIds) {
		// TODO Auto-generated method stub
		List<TTscClientRole> ttscClientRoleVOList = this.singleClientRoleObjectManager.findClientRolesByRoleIds(roleIds);
		List<ClientRoleVO> clientRoleVOList = new ArrayList<ClientRoleVO>();
		if(ttscClientRoleVOList != null && ttscClientRoleVOList.size()>0){
			for(TTscClientRole tclient : ttscClientRoleVOList){
				ClientRoleVO clientRole = new ClientRoleVO();
				this.getMapper().map(tclient, clientRole);
				clientRoleVOList.add(clientRole);
			}
			return clientRoleVOList;
		}else{
			return null;
		}
	}

	/**
	 * findServiceDepartmentsByDepartmentId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceDepartmentsByDepartmentId(java.util.List)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<DepartmentVO> findServiceDepartmentsByDepartmentId(List<String> departmentCodes) {
		// TODO Auto-generated method stub
		List<TTscDepartments> ttscDepartmentVOList = this.utilityDomainObjectManager.findServiceDepartmentsByDepartmentId(departmentCodes);
		List<DepartmentVO> departmentVOList = new ArrayList<DepartmentVO>();
		if(ttscDepartmentVOList != null && ttscDepartmentVOList.size() > 0){
			for(TTscDepartments tdept : ttscDepartmentVOList){
				DepartmentVO departmentVO = new DepartmentVO();
				this.getMapper().map(tdept, departmentVO);
				departmentVOList.add(departmentVO);
			}
			return departmentVOList;
		}else{
			return null;
		}
	}
	/**
	 * Description:
	 * updateWorkflowIncidentVO:	Method to update the LaunchIncidentVO based on the client roles the Service.
	 * This method finds the client roles of the Service, find its corresponding departments and sets the department flag in the LaunchIncidentVO
	 * By default, Finance Department is set to mandatory approval department, irrespective of the service role of the service 
	 * @author Dicetek.Ismail
	 * @param	LaunchIncidentVO - The workflow incident object which needs to be updated with the approval departments
	 * @param	- List<ServiceVO> - List of ServiceVO value objects which are selected for registration 
	 * 
	 */	
	@Transactional(readOnly = true)
	public void updateWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, List<ServiceVO> serviceVOs){
		if(launchIncidVO != null && serviceVOs != null ){
			List<String> strRoleIds = new ArrayList<String>();
			if(serviceVOs != null && serviceVOs.size() > 0){
				for(ServiceVO vo : serviceVOs){
					Service service = this.serviceDomainObjectManager.getServiceByPrimaryKey(vo.getStrServiceID());
					Set<ServiceRole> roleIds = service.getServiceRoles();
					if(roleIds != null){
						for(ServiceRole role : roleIds){
							strRoleIds.add(role.getRoleId().toString());
						}
					}
				}
			}
			// Find the departments linked to the roles from the TSC DB
			List<TTscClientRoleToDepartmentMap> departments = this.utilityDomainObjectManager.getDepartmentsByRoleIds(strRoleIds);
			if( departments == null ){
				departments = new ArrayList<TTscClientRoleToDepartmentMap>();
			}
			List<String> strDepartments = new ArrayList<String>();
			List<WorkflowDepartment> wfDepartments = new ArrayList<WorkflowDepartment>();
			for(TTscClientRoleToDepartmentMap deptMap : departments){
				TTscDepartments dept = deptMap.getDepartment();
				strDepartments.add(dept.getDeptCode().toUpperCase());
				wfDepartments.add(WorkflowDepartment.getWorkflowDepartmentfromString(dept.getDeptCode()));
			}
			// Add finance default by default for all the requests
			launchIncidVO.setgApprovalFIN(ConstantsCommon.SET_VALUE);
			if(strDepartments.contains(WorkflowDepartment.CED.getCode())){
				launchIncidVO.setgApprovalCED(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCED(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.CLD.getCode())){
				launchIncidVO.setgApprovalCLD(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCLD(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.EHS.getCode())){
				launchIncidVO.setgApprovalEHS(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalEHS(ConstantsCommon.UNSET_VALUE);
			}
		}
	}
	
		
	/**
	 * findServiceRolesByServiceType
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceRolesByServiceType(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceRoleVO> findServiceRolesByServiceType(String serviceType) {
		// TODO Auto-generated method stub
		List<ServiceRole> serviceRoleList = this.serviceDomainObjectManager.findServiceRolesByServiceType(serviceType);
		List<ServiceRoleVO> serviceRoleVOList = new ArrayList<ServiceRoleVO>();
		if(serviceRoleList != null && serviceRoleList.size()>0){
			for(ServiceRole role : serviceRoleList){
				ServiceRoleVO serviceRole = new ServiceRoleVO();
				this.getMapper().map(role, serviceRole);
				serviceRoleVOList.add(serviceRole);
			}
			return serviceRoleVOList;
		}else{
			return null;
		}	
	}

	/**
	 * registerInternalStaff
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#registerInternalStaff(ae.pcfc.etks.online.common.vo.UserVO, java.util.List)
	 * 
	 */
	@Transactional(readOnly = false)
	public void registerInternalStaff(UserVO userVO, List<Long> arrRoles) {
		// TODO Auto-generated method stub
		User user = userDomainObjectManager.findUserByUserName(userVO
				.getStrUsrName());
		if (user != null) {
			throw new DuplicateUserNameException(userVO.getStrUsrName());
		}else {
			User userdomain = new User();
			getMapper().map(userVO, userdomain);
			this.userDomainObjectManager.add(userdomain);
			registerUserRoles(userVO, arrRoles);
		}
		
	}
	/**
	 * Description:
	 * registerUserRoles:	Method to register user roles to the Internal Trakhees Staff in the system 
	 *
	 * @author Dicetek.Ismail
	 * @param	UserVO - Contains the information of the User obtained from the front end
	 * @param	List<Long> - Contains list of Role Ids to which the Internal Trakhees Staff needs to be associated with
	 * @return	- 
	 * 
	 */	
	private boolean registerUserRoles(UserVO userVO, List<Long> arrRoles){
		if(userVO != null){
			List<ServiceRole> roleList = null;
			if(arrRoles != null && arrRoles.size() > 0){
				roleList = this.serviceDomainObjectManager.findServiceRoleByRoleIds(arrRoles);
			}
			Service internalStaffDefaultService = this.serviceDomainObjectManager.findServiceByServiceDefault(ConstantsCommon.INTERNAL_STAFF_DEFAULT_SERVICE);
			if(roleList == null){
				roleList = new ArrayList<ServiceRole>();
			}
			if(roleList != null){
				Set<ServiceRole> userDefaultServiceRoles = internalStaffDefaultService.getServiceRoles();
				if(userDefaultServiceRoles != null){
					roleList.addAll(userDefaultServiceRoles);
				}
				for(ServiceRole role : roleList){
					UserServiceSecurity userServiceSecurity = new UserServiceSecurity();
					userServiceSecurity.setServiceRole(role);
					userServiceSecurity.setUsSecurityUsername(userVO.getStrUsrName());
					userServiceSecurity.setUsSecurityUserType(userVO.getStrType());
					userServiceSecurityDomainObjectManager.add(userServiceSecurity);
				}
			}
			return true;
		}else{
			return false;
		}
	}

	/**
	 * findServiceRolesByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#findServiceRolesByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ServiceRoleVO> findServiceRolesByUserName(String strUserName) {
		// TODO Auto-generated method stub
		List<ServiceRole> serviceRoleList = this.serviceDomainObjectManager.findServiceRolesByUserName(strUserName);
		List<ServiceRoleVO> serviceRoleVOList = new ArrayList<ServiceRoleVO>();
		if(serviceRoleList != null && serviceRoleList.size()>0){
			for(ServiceRole role : serviceRoleList){
				ServiceRoleVO serviceRole = new ServiceRoleVO();
				this.getMapper().map(role, serviceRole);
				serviceRoleVOList.add(serviceRole);
			}
			return serviceRoleVOList;
		}else{
			return null;
		}
	}

	/**
	 * updateInternalStaff
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ServiceFacade#updateInternalStaff(ae.pcfc.etks.online.common.vo.UserVO, java.util.List)
	 * 
	 */
	@Transactional(readOnly = false)
	public void updateInternalStaff(UserVO userVO, List<Long> arrRoles) {
		// TODO Auto-generated method stub
		/*User user = userDomainObjectManager.findUserByEmailExceptCurrentCompany(userVO.getStrEmail(), null);
		if (user != null) {
			throw new DuplicateUserEmailException(userVO.getStrEmail());
		} else {*/
			User userdomain = new User();
			getMapper().map(userVO, userdomain);
			this.userDomainObjectManager.update(userdomain);
			if(arrRoles == null){
				arrRoles = new ArrayList<Long>();
			}
			updateUserRoles(userVO, arrRoles);
		/*}*/
	}
	/**
	 * Description:
	 * updateUserRoles:	Method to update user roles of the Internal Trakhees Staff in the system 
	 *
	 * @author Dicetek.Ismail
	 * @param	UserVO - Contains the information of the User obtained from the front end
	 * @param	List<Long> - Contains list of Role Ids obtained from the front end
	 * @return	boolean - true on success, else false 
	 * 
	 */	
	private boolean updateUserRoles(UserVO userVO, List<Long> arrRoles){
		if(userVO != null){
			List<ServiceRole> feRoleList = new ArrayList<ServiceRole>();
			if(arrRoles != null && arrRoles.size()>0){
				feRoleList = this.serviceDomainObjectManager.findServiceRoleByRoleIds(arrRoles);
			}
			List<UserServiceSecurity> lSubSetUserServiceSecurity = new ArrayList<UserServiceSecurity>();
			//Exclude the default services from the selection, those will not get deleted
			List<UserServiceSecurity> dbUssList = userServiceSecurityDomainObjectManager.findByUserNameWithoutDefault(userVO.getStrUsrName(), new String[]{ConstantsCommon.INTERNAL_STAFF_DEFAULT_SERVICE});
			if(dbUssList == null){
				dbUssList = new ArrayList<UserServiceSecurity>();
			}
			if(feRoleList != null){
				for(ServiceRole role : feRoleList){
					UserServiceSecurity uss = findByServiceRoleAndUserName(
							dbUssList, role,
							userVO.getStrUserName());
					if (uss == null) {
						UserServiceSecurity userServiceSecurity = new UserServiceSecurity();
						userServiceSecurity.setServiceRole(role);
						userServiceSecurity.setUsSecurityUsername(userVO.getStrUsrName());
						userServiceSecurity.setUsSecurityUserType(userVO.getStrType());
						userServiceSecurityDomainObjectManager.add(userServiceSecurity);
					} else {
						lSubSetUserServiceSecurity.add(uss);
					}
				}
			}
			//Logic to find the list of already existing uss which are not in the list from the front end
			//Find the union of uss objects  and  subtract it from the uss objects from front end which already exist in db
			//from which we get the uss objects which existed in the db initially and now it is removed from the front end
			if (dbUssList != null) {
				@SuppressWarnings("unchecked")
				List<UserServiceSecurity> lUnionUserServiceSecurity = (List<UserServiceSecurity>) CommonUtils
						.union(dbUssList, lSubSetUserServiceSecurity);
				@SuppressWarnings("unchecked")
				List<UserServiceSecurity> lRemoveUserServiceSecurity = (List<UserServiceSecurity>) CommonUtils
						.subtract(lUnionUserServiceSecurity,
								lSubSetUserServiceSecurity);
				for (UserServiceSecurity uss : lRemoveUserServiceSecurity) {
					userServiceSecurityDomainObjectManager.delete(uss);
				}

			}
			return true;
		}else{
			return false;
		}
		
	}
	@Transactional(readOnly = true)
	public List<ProcessVO> getProcessList() {
		List<ae.pcfc.etks.online.common.domain.Process> processList = this.processDomainObjectManager.getAllProcesses();
		if(processList != null){
			List<ProcessVO> processVOs = new ArrayList<ProcessVO>();
			for(ae.pcfc.etks.online.common.domain.Process process:processList){
				ProcessVO processVO = new ProcessVO();
				this.getMapper().map(process, processVO);
				processVOs.add(processVO);
			}
			return processVOs;
		}
		return null;
	}



	@Transactional
	public void undoReviewRegisterService(AdminApprovalVO adminApprovalVO) {
		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO
				.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			adminApprovalVO.setStrApplnStatus(ConstantsCommon.IN_PROGRESS);
			getMapper().map(adminApprovalVO, appMetaData);
			
			this.appMetaDataDomainObjectManager.undoUpdateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());

			if(userServiceWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
			    	undoAddRequestedServices(adminApprovalVO);
			}
			appMetaData.setWfStatus(ConstantsCommon.IN_PROGRESS);
			appMetaData.setWfStatusEn(adminApprovalVO.getStrInProgressStatusEn());
			appMetaData.setWfStatusAr(adminApprovalVO.getStrInProgressStatusAr());
			appMetaDataDomainObjectManager.update(appMetaData);
		}
	}

	private void undoAddRequestedServices(AdminApprovalVO adminApprovalVO) {
		UserServiceSecurity userServiceSecurity;
		User user = null;
		List<ServiceReq> serviceReqs = this.serviceDomainObjectManager.findServiceReqByApplicationId(adminApprovalVO.getStrApplicationId());
		if(serviceReqs != null){
			Set<UserServiceSecurity> ussSet = new HashSet<UserServiceSecurity>();
			for (ServiceReq service : serviceReqs) {
				Client client = service.getUser().getClient();
				
				user = service.getUser();
				for (ServiceRole serviceRole : service.getService().getServiceRoles()) {
					List<ClientServiceRole> clientServiceRoles = this.serviceDomainObjectManager.findServiceRoleByClientAndRoleId(client, serviceRole.getSrId());
					if(clientServiceRoles != null){
						for(ClientServiceRole csr : clientServiceRoles){
							this.clientDomainObjectManager.delete(csr);
						}
					}
	
					userServiceSecurity = new UserServiceSecurity();
					userServiceSecurity.setServiceRole(serviceRole);
					userServiceSecurity.setUsSecurityUsername(user.getUUsername());
					userServiceSecurity.setUsSecurityUserType(user.getUType());

					List<UserServiceSecurity> ussList = this.userServiceSecurityDomainObjectManager.findUserServiceSecurity(userServiceSecurity);
					if(ussList != null){
					    ussSet.addAll(ussList);
					}
				}
			}
			for(UserServiceSecurity uss : ussSet){
				this.userServiceSecurityDomainObjectManager.delete(uss);
			}
		}		
	}
}
